package jobs

import (
	"errors"
	"fmt"
	"os"
	"strconv"

	md "gitee.com/countpoison/youbei/models"
	db "gitee.com/countpoison/youbei/utils/database"
	filedump "gitee.com/countpoison/youbei/utils/file"
	"gitee.com/countpoison/youbei/utils/mail"
	rs "gitee.com/countpoison/youbei/utils/rs"
	"github.com/segmentio/ksuid"
)

//ExecBackup ...
func ExecBackup(taskinfo *md.Task) (string, error) {
	t := taskinfo
	if t.DBType == "mysql" {
		return db.MysqlSQLDump(t.Host, t.Port, t.DBname, t.User, t.Password, t.Char, t.SavePath, t.Zippwd)
	} else if t.DBType == "mssql" {
		return db.MssqlSQLDump(t.Host, t.DBname, t.User, t.Password, t.SavePath, t.Zippwd)
	} else if t.DBType == "sqlite" {
		return db.SqliteSQLDump(t.DBpath, t.SavePath, t.Zippwd)
	} else if t.DBType == "postgres" {
		return db.PostgresSQLDump(t.Host, t.Port, t.DBname, t.User, t.Password, t.SavePath, t.Zippwd)
	} else if t.DBType == "file" {
		return filedump.FileDump(t.DBpath, t.SavePath, t.Zippwd)
	}
	return "", errors.New("dbtype not found")
}

//ExecRemote ...
func ExecRemote(v md.RemoteStorage, rlid string, lid string, Localfilepath string) error {
	fmt.Println("测试手动执行")
	var err error
	yuancheng := rs.NewRS(v.Host, v.Port, v.Username, v.Password, Localfilepath, v.Path)
	if v.Types == "ftp" {
		err = yuancheng.FtpUpload()
	} else if v.Types == "sftp" {
		f, err := yuancheng.NewSftp()
		if err == nil {
			err = f.Upload()
		}
	} else if v.Types == "Yserver" {
		fmt.Println("测试手动执行1")
		filepackets, err := yuancheng.ReadBigFile()
		if err != nil {
			fmt.Println(err.Error())
			return err
		}
		ysuploadfile := new(md.YsUploadFile)
		ysuploadfile.ID = ksuid.New().String()
		ysuploadfile.Lid = rlid
		fmt.Println("测试手动执行2")
		fmt.Println(filepackets.SrcFilePath)
		fmt.Println("测试手动执行3")
		ysuploadfile.SrcFilePath = filepackets.SrcFilePath
		ysuploadfile.UploadFileServerID = filepackets.UploadFileServerID
		ysuploadfile.Size = filepackets.Size
		fmt.Println("测试手动执行4")
		ysuploadfile.PacketNum = filepackets.PacketNum
		if err = ysuploadfile.AddYsFileLog(err); err != nil {
			return err
		}
		fmt.Println("测试手动执行5")
		for _, v := range filepackets.Packets {
			packetlog := md.YsPacket{}
			packetlog.ID = ksuid.New().String()
			packetlog.Yid = ysuploadfile.ID
			packetlog.Offset = v.Offset
			packetlog.Status = 1
			packetlog.SortID = v.SortID
			packetlog.SrcPacketPath = v.Packetpath
			packetlog.UploadPacketURL = filepackets.PacketUploadURL + strconv.Itoa(v.SortID)
			if err = ysuploadfile.AddYsPacketLog(packetlog); err != nil {
				fmt.Println(err.Error())
			}
		}
		fmt.Println("测试手动执行6")
		file, err := os.OpenFile(filepackets.SrcFilePath, os.O_RDONLY, os.ModePerm)
		if err != nil {
			for _, v := range filepackets.Packets {
				ysuploadfile.UpdateYspacketLog(v.SortID, err)
			}
			filepackets.UploadDone("2")
			return err
		}
		defer file.Close()
		alldoneerr := 0
		for _, v := range filepackets.Packets {
			err := ysuploadfile.UpdateYspacketLog(v.SortID, filepackets.CreatePacket(file, v))
			if err != nil {
				alldoneerr++
			}
			ysuploadfile.UpdateYspacketLog(v.SortID, err)
		}
		if alldoneerr > 0 {
			filepackets.UploadDone("2")
		} else {
			fmt.Println(123)
			filepackets.UploadDone("0")
		}

	}
	fmt.Println("测试手动执行7")
	return err
}

//Backup ...
func Backup(TaskID string, nowreturn bool) error {
	t := md.Task{}
	t.ID = TaskID
	if err := t.Select(); err != nil {
		return err
	}

	localfilepath, err := ExecBackup(&t)
	if err != nil {
		_, err := md.NewLog(TaskID, localfilepath, err.Error())
		if err != nil {
			return err
		}
		return err
	}

	LogID, err := md.NewLog(TaskID, localfilepath, "")
	if err != nil {
		return err
	}

	if RS, err := md.TaskFindRemote(TaskID); err != nil {
		return err
	} else {
		for _, v := range RS {
			remoteSendLog, err := md.AddNewRemoteSendLog(LogID, TaskID, v.ID)
			if err != nil {
				return err
			}
			err = ExecRemote(v, remoteSendLog.ID, LogID, localfilepath)
			remoteSendLog.Update(err)
		}
	}

	var reerr error
	task := md.Task{}
	task.ID = TaskID
	if _, err := md.Localdb().Get(&task); err == nil {
		ExpireDelete(TaskID, task.Expire)
	}
	return reerr

}

//Jobs ...
func Jobs(i string) func() error {
	return func() error {
		err := Backup(i, false)
		if err != nil {
			m := new(mail.MailConn)
			m.SendMail("备份失败", err.Error())
		}

		return nil
	}
}
